#ifndef TEST_SCHEME_H
#define TEST_SCHEME_H

#include "prng.h"
#include "encryptor.h"
#include "utils.h"
#include "context.h"
#include "ring_scaling.h"
#include "ring.h"
#include "ring_poly.h"
#include "operand.h"
#include "ring_sampler.h"
#include "keygen.h"
#include "ring_basis_extension.h"
#include "modular_reduction.h"
#include "encryptor.h"
#include "decryptor.h"
#include "evaluator.h"
#include "bootstrapping/bootstrapping.h"
#include "bootstrapping/karatsuba.h"


#include <string>
#include <stdexcept>

const double DefaultSigma = 3.2;
/* *
 * @class TestScheme
 * @brief 用于测试同态加密方案的各种功能，特别是针对BFV加密方案的各个操作。
 *
 * `TestScheme`
 * 类提供了多种加密方案的测试，包括加密、解密、密钥生成、多项式运算等。通过该类可以验证加密算法的各项操作是否正确。
 */
class TestScheme {
public:
    // 定义TestContext结构
    struct TestContext {
        Context *params;
        Ring *ringQ;
        Ring *ringP;
        Ring *ringQP;
        Ring *ringT;
        KeyedPRNG *prng;
        UniformSampler *uSampler;
        Encoder *encoder;
        KeyGenerator *kgen;
        SecretKey *sk;
        PublicKey *pk;
        RelinearizationKey *rlk;
        Encryptor *encryptorPk;
        Encryptor *encryptorSk;
        Decryptor *decryp;
        Evaluator *evaluator;
    };

    // 构造函数
    TestScheme() = default;
    // 拷贝构造函数
    TestScheme(const TestScheme &other) = delete;
    TestScheme &operator = (const TestScheme &other) = delete;
    // 移动构造函数
    TestScheme(TestScheme &&other) = delete;
    TestScheme &operator = (TestScheme &&other) = delete;

    Context* GetParams(long logN, int lambda);

    void TestPolyMult();

    void TestRotate();

    void TestBootstrapping();

    // 测试BFV的主函数
    void TestBFV();

    // 测试128位主函数
    void Test128BFV();

    // 测试加密、解密、密钥生成
    void TestEncrypt();

    void TestSkEncrypt();

    void TestMultRelin();

    void TestMultSquare();

    void TestMultRepeat();

    void TestMulPt();

    void TestAddPt();

    void TestAddCt();

    void TestSwitchKey();

    void TestRotateTime();


private:

    void GetPrimes(uint64_t logN, uint64_t bit, 
    vector<uint64_t>& qVec, vector<uint64_t>& pVec, int L, int K);

    // 生成测试上下文
    TestContext *GenTestParams(Context *params);

    // 新建测试向量
    static void *NewTestVectorsRingQ(TestContext *testctx, Encryptor *encryptor, Poly *&coeffs, Plaintext *plaintext);


    static PlaintextRingT *NewTestVectorsRingT(TestContext *testctx, Poly *&coeffs);


    // 验证测试向量
    void VerifyTestVectors(TestContext *testctx, Decryptor *decryptor, Poly *coeffs, Ciphertext *element);

    // 验证128测试向量
    void VerifyTestVectors128(TestContext *testctx, Decryptor *decryptor, Poly *coeffs, Ciphertext *element,
        SlotRing *slotRing);

    // 测试评估器
    void TestEvaluator(TestContext *testctx);

    // 测试128槽的旋转
    void TestRotate128(TestContext *testctx);

    // 测试评估器(针对128槽)
    void TestEvaluator128(TestContext *testctx);
};

#endif // TEST_SCHEME_H
